#pragma once

#include "SocketTemplate.hpp"

namespace TcpServerModule
{
    using namespace SocketModule;
    using tcphandler_t = function<bool(SockPtr, InetAddr)>;

    // 是他只进行IO，流式的IO，不对协议进行任何处理
    class TcpServer
    {
    public:
        TcpServer(int port)
            :_listensockp(std::make_unique<TcpSocket>())
            ,_isrunning(false)
            ,_port(port)
        {}

        void initServer(tcphandler_t handler)
        {
            _handler = handler;
            // 调用模板方法，启动tcp
            _listensockp->BuildTcpSocketMethod(_port);
        }

        // 服务器循环运行
        void Loop()
        {
            _isrunning = true;
            while(_isrunning)
            {
                // Accept
                InetAddr client;
                auto sockfd = _listensockp->Accepter(&client);
                if(sockfd == nullptr) continue;
                // IO处理
                LOG(LogLevel::DEBUG) << "Get a new info, info is: " << client.Addr();
                // sockfd->Recv()
                // sockfd->Send()
                pid_t id = fork();
                if(id == 0)
                {
                    // 子进程
                    _listensockp->Close();
                    if(fork() > 0) exit(0);
                    _handler(sockfd, client);
                    exit(0);
                }
                sockfd->Close();
                waitpid(id, nullptr, 0); 
            }
            _isrunning = false;
        }

        ~TcpServer()
        {
            _listensockp->Close();
        }
    private:
        std::unique_ptr<Socket> _listensockp;  // tcp一定要有一个监听套接字
        bool _isrunning;  // 服务器是否运行
        tcphandler_t _handler;  // 处理函数
        uint16_t _port;  // 端口号
    };
}